package com.cs.game.core.view.imageview;

import com.cs.game.core.constant.Constants;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

import java.util.ArrayList;

/**
 * Animal Actor class, including image rendering for animals, time monitoring, and logical judgment of games
 */
public class Animal extends Actor {
    Image imgW1;
    Image imgA1;
    Image imgS1;
    Image imgD1;
    Image imgW2;
    Image imgA2;
    Image imgS2;
    Image imgD2;
    int points = 0;
    int end = 0;
    private boolean second = false;
    /**
     * Whether the frog can move
     */
    private boolean canMove = false;
    /**
     * Whether a round of games failed
     */
    private boolean failed = false;
    boolean noMove = false;
    double movement = 13.3333333 * 2;
    double movementX = 10.666666 * 2;
    int imgSize = 40;
    boolean carDeath = false;
    boolean waterDeath = false;
    boolean stop = false;
    boolean changeScore = false;
    int carD = 0;
    double w = 800;
    ArrayList<End> inter = new ArrayList<End>();

    /**
     * Initialize the frog's jumping action process
     * Add time listener for keyboard press and release, event handling for W, A, S, D four buttons
     * W: Jump forward, A: Jump left, S: Jump backward, D: Jump right
     * @param imageLink
     */
    public Animal(String imageLink) {
        setImage(new Image(imageLink, imgSize, imgSize, true, true));
        setX(300);
        setY(679.8 + movement);
        ClassLoader classLoader = this.getClass().getClassLoader();
        String imgFroggerUp = classLoader.getResource(Constants.IMAGE_FROGGERUP_PATH).toString();
        String imgFroggerLeft = classLoader.getResource(Constants.IMAGE_FROGGERLEFT_PATH).toString();
        String imgFroggerDown = classLoader.getResource(Constants.IMAGE_FROGGERDOWN_PATH).toString();
        String imgFroggerRight = classLoader.getResource(Constants.IMAGE_FROGGERRIGHT_PATH).toString();
        String imgFroggerUpJump = classLoader.getResource(Constants.IMAGE_FROGGERUPJUMP_PATH).toString();
        String imgFroggerLeftJump = classLoader.getResource(Constants.IMAGE_FROGGERLEFTJUMP_PATH).toString();
        String imgFroggerDownJump = classLoader.getResource(Constants.IMAGE_FROGGERDOWNJUMP_PATH).toString();
        String imgFroggerRightJump = classLoader.getResource(Constants.IMAGE_FROGGERRIGHTJUMP_PATH).toString();

        imgW1 = new Image(imgFroggerUp, imgSize, imgSize, true, true);
        imgA1 = new Image(imgFroggerLeft, imgSize, imgSize, true, true);
        imgS1 = new Image(imgFroggerDown, imgSize, imgSize, true, true);
        imgD1 = new Image(imgFroggerRight, imgSize, imgSize, true, true);
        imgW2 = new Image(imgFroggerUpJump, imgSize, imgSize, true, true);
        imgA2 = new Image(imgFroggerLeftJump, imgSize, imgSize, true, true);
        imgS2 = new Image(imgFroggerDownJump, imgSize, imgSize, true, true);
        imgD2 = new Image(imgFroggerRightJump, imgSize, imgSize, true, true);
        setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if(!canMove) {
                    return;
                }
                if (noMove) {

                } else {
                    if (second) {
                        if (event.getCode() == KeyCode.W) {
                            move(0, -movement);
                            changeScore = false;
                            setImage(imgW1);
                            second = false;
                        } else if (event.getCode() == KeyCode.A) {
                            move(-movementX, 0);
                            setImage(imgA1);
                            second = false;
                        } else if (event.getCode() == KeyCode.S) {
                            move(0, movement);
                            setImage(imgS1);
                            second = false;
                        } else if (event.getCode() == KeyCode.D) {
                            move(movementX, 0);
                            setImage(imgD1);
                            second = false;
                        }
                    } else if (event.getCode() == KeyCode.W) {
                        move(0, -movement);
                        setImage(imgW2);
                        second = true;
                    } else if (event.getCode() == KeyCode.A) {
                        move(-movementX, 0);
                        setImage(imgA2);
                        second = true;
                    } else if (event.getCode() == KeyCode.S) {
                        move(0, movement);
                        setImage(imgS2);
                        second = true;
                    } else if (event.getCode() == KeyCode.D) {
                        move(movementX, 0);
                        setImage(imgD2);
                        second = true;
                    }
                }
            }
        });
        setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if(!canMove) {
                    return;
                }
                if (noMove) {
                } else {
                    if (event.getCode() == KeyCode.W) {
                        if (getY() < w) {
                            changeScore = true;
                            w = getY();
                            points += 10;
                        }
                        move(0, -movement);
                        setImage(imgW1);
                        second = false;
                    } else if (event.getCode() == KeyCode.A) {
                        move(-movementX, 0);
                        setImage(imgA1);
                        second = false;
                    } else if (event.getCode() == KeyCode.S) {
                        move(0, movement);
                        setImage(imgS1);
                        second = false;
                    } else if (event.getCode() == KeyCode.D) {
                        move(movementX, 0);
                        setImage(imgD1);
                        second = false;
                    }
                }
            }

        });
    }

    /**
     * Logic judgment based on animal position
     * When an animal is hit by a car or waterDeath, this round of the game fails and a score window pops up
     * When the game is completed, the game ends and the game victory window pops up
     * @see com.cs.game.core.Main#createTimer
     *
     * @param now
     */
    @Override
    public void act(long now) {
        int bounds = 0;
        ClassLoader classLoader = this.getClass().getClassLoader();
        if (getY() < 0 || getY() > 734) {
            setX(300);
            setY(679.8 + movement);
        }
        if (getX() < 0) {
            move(movement * 2, 0);
        }
        if (carDeath) {
            noMove = true;
            if ((now) % 11 == 0) {
                carD++;
            }
            if (carD == 1) {
                String imgCardeath1 = classLoader.getResource(Constants.IMAGE_CARDEATH1_PATH).toString();
                setImage(new Image(imgCardeath1, imgSize, imgSize, true, true));
            }
            if (carD == 2) {
                String imgCardeath2 = classLoader.getResource(Constants.IMAGE_CARDEATH2_PATH).toString();
                setImage(new Image(imgCardeath2, imgSize, imgSize, true, true));
            }
            if (carD == 3) {
                String imgCardeath3 = classLoader.getResource(Constants.IMAGE_CARDEATH3_PATH).toString();
                setImage(new Image(imgCardeath3, imgSize, imgSize, true, true));
            }
            if (carD == 4) {
                setX(300);
                setY(679.8 + movement);
                carDeath = false;
                carD = 0;
                String imgFroggerUp = classLoader.getResource(Constants.IMAGE_FROGGERUP_PATH).toString();
                setImage(new Image(imgFroggerUp, imgSize, imgSize, true, true));
                noMove = false;
                if (points > 50) {
                    points -= 50;
                    changeScore = true;
                }
            }
            this.setFailed(true);

        }
        if (waterDeath) {
            noMove = true;
            if ((now) % 11 == 0) {
                carD++;
            }
            if (carD == 1) {
                String imgWaterdeath1 = classLoader.getResource(Constants.IMAGE_WATERDEATH1_PATH).toString();
                setImage(new Image(imgWaterdeath1, imgSize, imgSize, true, true));
            }
            if (carD == 2) {
                String imgWaterdeath2 = classLoader.getResource(Constants.IMAGE_WATERDEATH2_PATH).toString();
                setImage(new Image(imgWaterdeath2, imgSize, imgSize, true, true));
            }
            if (carD == 3) {
                String imgWaterdeath3 = classLoader.getResource(Constants.IMAGE_WATERDEATH3_PATH).toString();
                setImage(new Image(imgWaterdeath3, imgSize, imgSize, true, true));
            }
            if (carD == 4) {
                String imgWaterdeath4 = classLoader.getResource(Constants.IMAGE_WATERDEATH4_PATH).toString();
                setImage(new Image(imgWaterdeath4, imgSize, imgSize, true, true));
            }
            if (carD == 5) {
                setX(300);
                setY(679.8 + movement);
                waterDeath = false;
                carD = 0;
                String imgFroggerUp = classLoader.getResource(Constants.IMAGE_FROGGERUP_PATH).toString();
                setImage(new Image(imgFroggerUp, imgSize, imgSize, true, true));
                noMove = false;
                if (points > 50) {
                    points -= 50;
                    changeScore = true;
                }
            }
            this.setFailed(true);

        }

        if (getX() > 600) {
            move(-movement * 2, 0);
        }
        if (getIntersectingObjects(Obstacle.class).size() >= 1) {
            carDeath = true;
        }
        if (getX() == 240 && getY() == 82) {
            stop = true;
        }
        if (getIntersectingObjects(Log.class).size() >= 1 && !noMove) {
            if (getIntersectingObjects(Log.class).get(0).getLeft()) {
                move(-2, 0);
            } else {
                move(.75, 0);
            }
        } else if (getIntersectingObjects(Turtle.class).size() >= 1 && !noMove) {
            move(-1, 0);
        } else if (getIntersectingObjects(WetTurtle.class).size() >= 1) {
            if (getIntersectingObjects(WetTurtle.class).get(0).isSunk()) {
                waterDeath = true;
            } else {
                move(-1, 0);
            }
        } else if (getIntersectingObjects(End.class).size() >= 1) {
            inter = (ArrayList<End>) getIntersectingObjects(End.class);
            if (getIntersectingObjects(End.class).get(0).isActivated()) {
                end--;
                points -= 50;
            }
            points += 50;
            changeScore = true;
            w = 800;
            getIntersectingObjects(End.class).get(0).setEnd();
            end++;
            setX(300);
            setY(679.8 + movement);
        } else if (getY() < 413) {
            waterDeath = true;
            //setX(300);
            //setY(679.8+movement);
        }
    }

    /**
     * If the number of frogs reaching the end point is equal to 5, the user wins the game and the game ends
     * @return
     */
    public boolean getStop() {
        return end == 5;
    }

    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points < 0 ? 0 : points;
    }

    public boolean changeScore() {
        if (changeScore) {
            changeScore = false;
            return true;
        }
        return false;

    }

    public boolean isCanMove() {
        return canMove;
    }

    public void setCanMove(boolean canMove) {
        this.canMove = canMove;
    }

    public boolean isFailed() {
        return failed;
    }

    public void setFailed(boolean failed) {
        this.failed = failed;
    }
}
